home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Leser 19 / Amiga Plus Leser CD 19.iso / Tools / Freeware / Swf_Player / Lib / graphic.cc < prev    next >
Encoding:
C/C++ Source or Header  |  2002-11-17  |  14.2 KB  |  633 lines

  1. ////////////////////////////////////////////////////////////
  2. // Flash Plugin and Player
  3. // Copyright (C) 1998 Olivier Debon
  4. // 
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9. // 
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14. // 
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18. // 
  19. ///////////////////////////////////////////////////////////////
  20. //  Author : Olivier Debon  <odebon@club-internet.fr>
  21. //  
  22.  
  23. #include "swf.h"
  24.  
  25. #ifdef RCSID
  26. static char *rcsid = "$Id: graphic.cc,v 1.5 1999/09/03 15:17:40 ode Exp $";
  27. #endif
  28.  
  29. #define PRINT 0
  30.  
  31. // Public
  32.  
  33. GraphicDevice::GraphicDevice(FlashDisplay *fd)
  34. {
  35.     flashDisplay = fd;
  36.  
  37.     bgInitialized = 0;
  38.  
  39.     // Reset flash refresh flag
  40.     flashDisplay->flash_refresh = 0;
  41.  
  42.         /* 16 bits, RGB565 */
  43.     redMask = 0xF800;
  44.     greenMask = 0x07E0;
  45.     blueMask = 0x001F;
  46.  
  47.         /* should be the actual window size */
  48.     targetWidth = fd->width;
  49.     targetHeight = fd->height;
  50.         bpl = fd->bpl;
  51.  
  52. #if PRINT
  53.     printf("Target Width  = %d\n", targetWidth);
  54.     printf("Target Height = %d\n", targetHeight);
  55. #endif
  56.  
  57.     zoom = FRAC;
  58.     movieWidth = targetWidth;
  59.     movieHeight = targetHeight;
  60.  
  61.     viewPort.xmin = 0;
  62.     viewPort.xmax = targetWidth-1;
  63.     viewPort.ymin = 0;
  64.     viewPort.ymax = targetHeight-1;
  65.  
  66.     canvasBuffer = (unsigned char *) fd->pixels;
  67.  
  68.     adjust = new Matrix;
  69.     foregroundColor.red = 0;
  70.     foregroundColor.green = 0;
  71.     foregroundColor.blue = 0;
  72.     foregroundColor.alpha = ALPHA_OPAQUE;
  73.  
  74.     backgroundColor.red = 0;
  75.     backgroundColor.green = 0;
  76.     backgroundColor.blue = 0;
  77.     backgroundColor.alpha = ALPHA_OPAQUE;
  78.  
  79.     showMore = 0;
  80.  
  81.     setClipping(0);    // Reset
  82.     setClipping(1);
  83.  
  84.         /* polygon rasterizer : handle memory errors ! */
  85.  
  86.         height = targetHeight;
  87.         segs = (Segment **)malloc(height * sizeof(Segment *));
  88.         memset(segs, 0, height * sizeof(Segment *));
  89.         ymin = height;
  90.         ymax = -1;
  91.  
  92.         seg_pool = (Segment *)malloc(NB_SEGMENT_MAX * sizeof(Segment));
  93.         seg_pool_cur = seg_pool;
  94. }
  95.  
  96. GraphicDevice::~GraphicDevice()
  97. {
  98.     free(segs);
  99.     free(seg_pool);
  100.     
  101.     if (adjust) {
  102.         delete adjust;
  103.     }
  104. }
  105.  
  106. Color *
  107. GraphicDevice::getColormap(Color *old, long n, Cxform *cxform)
  108. {
  109.     Color *newCmp;
  110.  
  111.     newCmp = new Color[n];
  112.     if (newCmp == NULL) return NULL;
  113.  
  114.     if (cxform) {
  115.         for(long i = 0; i < n; i++)
  116.         {
  117.             newCmp[i] = cxform->getColor(old[i]);
  118.             newCmp[i].pixel = allocColor(newCmp[i]);
  119.         }
  120.     } else {
  121.         for(long i = 0; i < n; i++)
  122.         {
  123.             newCmp[i] = old[i];
  124.             newCmp[i].pixel = allocColor(old[i]);
  125.         }
  126.     }
  127.  
  128.     return newCmp;
  129. }
  130.  
  131. long
  132. GraphicDevice::getHeight()
  133. {
  134.     return targetHeight;
  135. }
  136.  
  137. long
  138. GraphicDevice::getWidth()
  139. {
  140.     return targetWidth;
  141. }
  142.  
  143. Color
  144. GraphicDevice::getForegroundColor()
  145. {
  146.     return foregroundColor;
  147. }
  148.  
  149. void
  150. GraphicDevice::setForegroundColor(Color color)
  151. {
  152.     foregroundColor = color;
  153. }
  154.  
  155. Color
  156. GraphicDevice::getBackgroundColor()
  157. {
  158.     return backgroundColor;
  159. }
  160.  
  161. int
  162. GraphicDevice::setBackgroundColor(Color color)
  163. {
  164.     if (bgInitialized == 0) {
  165.         backgroundColor = color;
  166.         clearCanvas();
  167.         bgInitialized = 1;
  168.         return 1;
  169.     }
  170.     return 0;
  171. }
  172.  
  173. void
  174. GraphicDevice::setMovieDimension(long width, long height)
  175. {
  176.     float xAdjust, yAdjust;
  177.  
  178.     movieWidth = width;
  179.     movieHeight = height;
  180.  
  181.     xAdjust = (float)targetWidth*zoom/(float)width;
  182.     yAdjust = (float)targetHeight*zoom/(float)height;
  183.  
  184.     if (xAdjust < yAdjust) {
  185.         adjust->a = xAdjust;
  186.         adjust->d = xAdjust;
  187.                 adjust->ty = ((targetHeight*zoom) - (long)(height * xAdjust))/2;
  188.         viewPort.ymin = adjust->ty/zoom;
  189.         viewPort.ymax = targetHeight-viewPort.ymin-1;
  190.     } else {
  191.         adjust->a = yAdjust;
  192.         adjust->d = yAdjust;
  193.                 adjust->tx = ((targetWidth*zoom) - (long)(width * yAdjust))/2;
  194.         viewPort.xmin = adjust->tx/zoom;
  195.         viewPort.xmax = targetWidth-viewPort.xmin-1;
  196.     }
  197.  
  198.     if (viewPort.xmin < 0) viewPort.xmin = 0;
  199.     if (viewPort.ymin < 0) viewPort.ymin = 0;
  200.     if (viewPort.xmax >= targetWidth) viewPort.xmax = targetWidth-1;
  201.     if (viewPort.ymax >= targetHeight) viewPort.ymax = targetHeight-1;
  202. }
  203.  
  204. void
  205. GraphicDevice::setMovieZoom(int z)
  206. {
  207.     z *= FRAC;
  208.     if (z <= 0 || z > 100) return;
  209.     zoom = z;
  210.     setMovieDimension(movieWidth,movieHeight);
  211. }
  212.  
  213. void
  214. GraphicDevice::setMovieOffset(long x, long y)
  215. {
  216.     adjust->tx = -zoom*x;
  217.     adjust->ty = -zoom*y;
  218. }
  219.  
  220. long
  221. GraphicDevice::clip(long &y, long &start, long &end)
  222. {
  223.     long xmin,xend;
  224.  
  225.     if (y < clip_rect.ymin ||
  226.         y >= clip_rect.ymax) return 1;
  227.     if (end <= start)
  228.         return 1;
  229.     xmin = clip_rect.xmin * FRAC;
  230.     xend = clip_rect.xmax * FRAC;
  231.  
  232.     if (end <= xmin || start >= xend) return 1;
  233.  
  234.     if (start < xmin) start = xmin;
  235.     if (end > xend) end = xend;
  236.  
  237.     return 0;
  238. }
  239.  
  240. void
  241. GraphicDevice::drawBox(long x1, long y1, long x2, long y2)
  242. {
  243.     int i;
  244.  
  245.     for(i=0;i<FRAC*2;i++) {
  246.         drawLine(x1+i, y1+i, x2-i, y1+i, 0);
  247.         drawLine(x1+i, y2-i, x2-i, y2-i, 0);
  248.  
  249.         drawLine(x1+i, y1+i+1, x1+i, y2-i-1, 0);
  250.         drawLine(x2-i, y1+i+1, x2-i, y2-i-1, 0);
  251.     }
  252. }
  253.  
  254. /* polygon rasteriser */
  255.  
  256. inline Segment *
  257. GraphicDevice::allocSeg()
  258. {
  259.     Segment *seg;
  260.  
  261.     if ( (seg_pool_cur - seg_pool) >= NB_SEGMENT_MAX )
  262.         return NULL;
  263.     seg = seg_pool_cur++;
  264.  
  265.     return seg;
  266. }
  267.  
  268. /* add a segment to the current path */
  269. void
  270. GraphicDevice::addSegment(long x1, long y1, long x2, long y2,
  271.                           FillStyleDef *f0,
  272.                           FillStyleDef *f1,
  273.                           int aa)
  274. {
  275.     Segment *seg,**segs;
  276.     long dX, X, Y, ymin, ymax, tmp;
  277.     FillStyleDef *ff;
  278.  
  279.     if ( y1 == y2 ) {
  280.         return;
  281.     }
  282.  
  283.     if (y1 < y2) {
  284.         ymin = y1;
  285.         ymax = y2;
  286.         ff = f0;
  287.         f0 = f1;
  288.         f1 = ff;
  289.     } else {
  290.         ymin = y2;
  291.         ymax = y1;
  292.         tmp = x1;
  293.         x1 = x2;
  294.         x2 = tmp;
  295.     }
  296.  
  297.     if (ymax>>FRAC_BITS < clip_rect.ymin) {
  298.         return;
  299.     }
  300.     if (ymin>>FRAC_BITS > clip_rect.ymax) {
  301.         return;
  302.     }
  303.  
  304.     X = x1 << SEGFRAC;
  305.     dX = ((x2 - x1)<<SEGFRAC)/(ymax-ymin);
  306.  
  307.     if (ymin < 0) {
  308.         X += dX * (-ymin);
  309.         ymin = 0;
  310.     }
  311.  
  312.     Y = (ymin + (FRAC-1)) & ~(FRAC-1);
  313.     if (Y > ymax) {
  314.         //printf("Elimine @ y = %d   ymin = %d, ymax = %d\n", Y, ymin, seg->ymax);
  315.         return;
  316.     }
  317.     X += dX * (Y-ymin);
  318.  
  319.     Y >>= FRAC_BITS;
  320.     if (Y >= clip_rect.ymax) {
  321.         return;
  322.     }
  323.  
  324.     seg = allocSeg();
  325.     if (seg == NULL) {
  326.         return;
  327.     }
  328.  
  329.     seg->next = 0;
  330.     seg->nextValid = 0;
  331.     seg->aa = aa;
  332.     seg->ymax = ymax;
  333.     seg->x1 = x1;
  334.     seg->x2 = x2;
  335.     seg->X = X;
  336.     seg->dX = dX;
  337.     seg->fs[0] = f0;
  338.     seg->fs[1] = f1;
  339.  
  340.     if (Y < this->ymin) this->ymin = Y;
  341.     ymax = (seg->ymax + FRAC - 1) >> FRAC_BITS;
  342.     if (ymax >= this->height) ymax = this->height-1;
  343.     if (ymax > this->ymax) this->ymax = ymax;
  344.  
  345.     segs = this->segs;
  346.  
  347.     if (segs[Y] == 0) {
  348.         segs[Y] = seg;
  349.     } else {
  350.         Segment *s,*prev;
  351.  
  352.         prev = 0;
  353.         for(s = segs[Y]; s; prev = s, s = s->next) {
  354.             if (s->X > seg->X) {
  355.                 if (prev) {
  356.                     prev->next = seg;
  357.                     seg->next = s;
  358.                 } else {
  359.                     seg->next = segs[Y];
  360.                     segs[Y] = seg;
  361.                 }
  362.                 break;
  363.             }
  364.         }
  365.         if (s == 0) {
  366.             prev->next = seg;
  367.             seg->next = s;
  368.         }
  369.     }
  370. }
  371.  
  372. inline Segment *
  373. GraphicDevice::progressSegments(Segment * curSegs, long y)
  374. {
  375.     Segment *seg,*prev;
  376.  
  377.     // Update current segments
  378.     seg = curSegs;
  379.     prev = 0;
  380.     while(seg)
  381.     {
  382.         if ((y*FRAC) > seg->ymax) {
  383.             // Remove this segment, no more valid
  384.             if (prev) {
  385.                 prev->nextValid = seg->nextValid;
  386.             } else {
  387.                 curSegs = seg->nextValid;
  388.             }
  389.             seg = seg->nextValid;
  390.         } else {
  391.             seg->X += seg->dX * FRAC;
  392.             prev = seg;
  393.             seg = seg->nextValid;
  394.         }
  395.     }
  396.     return curSegs;
  397. }
  398.  
  399. inline Segment *
  400. GraphicDevice::newSegments(Segment *curSegs, Segment *newSegs)
  401. {
  402.     Segment *s,*seg,*prev;
  403.  
  404.     s = curSegs;
  405.     prev = 0;
  406.  
  407.     // Check for new segments
  408.     for (seg = newSegs; seg; seg=seg->next)
  409.     {
  410.         // Place it at the correct position according to X
  411.         if (curSegs == 0) {
  412.             curSegs = seg;
  413.             seg->nextValid = 0;
  414.         } else {
  415.             for(; s; prev = s, s = s->nextValid)
  416.             {
  417.                 if ( s->X > seg->X ||
  418.                      ( (s->X == seg->X) && 
  419.                        ( (seg->x1 == s->x1 && seg->dX < s->dX) ||
  420.                          (seg->x2 == s->x2 && seg->dX > s->dX)
  421.                          ))) {
  422.                     // Insert before s
  423.                     if (prev) {
  424.                         seg->nextValid = s;
  425.                         prev->nextValid = seg;
  426.                     } else {
  427.                         seg->nextValid = curSegs;
  428.                         curSegs = seg;
  429.                     }
  430.                     break;
  431.                 }
  432.             }
  433.             // Append at the end
  434.             if (s == 0) {
  435.                 prev->nextValid = seg;
  436.                 seg->nextValid = 0;
  437.             }
  438.         }
  439.  
  440.         s = seg;
  441.     }
  442.  
  443.     return curSegs;
  444. }
  445.  
  446. #if 0
  447. static void
  448. printSeg(Segment *seg)
  449. {
  450.     /*
  451.     printf("Seg %08x : X = %5d, Ft = %d, Cl = %2x/%2x/%2x, Cr = %2x/%2x/%2x, x1=%5d, x2=%5d, ymin=%5d, ymax=%5d\n", seg,
  452.         seg->X>>SEGFRAC,
  453.         seg->right ? seg->right->type: -1,
  454.         seg->left ? seg->left->color.red : -1,
  455.         seg->left ? seg->left->color.green : -1,
  456.         seg->left ? seg->left->color.blue : -1,
  457.         seg->right ? seg->right->color.red : -1,
  458.         seg->right ? seg->right->color.green : -1,
  459.         seg->right ? seg->right->color.blue : -1,
  460.         seg->x1, seg->x2, seg->ymin, seg->ymax);
  461.     */
  462. }
  463. #endif
  464.  
  465. inline void
  466. GraphicDevice::renderScanLine(long y, Segment *curSegs)
  467. {
  468.     Segment *seg;
  469.     long width;
  470.     int fi = 1;
  471.     FillStyleDef *f;
  472.  
  473.     width = targetWidth * FRAC;
  474.  
  475.     if (curSegs && curSegs->fs[0] && curSegs->fs[1] == 0) {
  476.         fi = 0;
  477.     }
  478.     for(seg = curSegs; seg && seg->nextValid; seg = seg->nextValid)
  479.     {
  480.         if (seg->nextValid->X <0) continue;
  481.         if ((seg->X>>SEGFRAC) > width) break;
  482.         f = seg->fs[fi];
  483.         if (f) {
  484.             switch (f->type) {
  485.                 case f_Solid:
  486.                     if (seg->aa) {
  487.                         fillLineAA(f, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC);
  488.                     } else  {
  489.                         fillLine(f, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC);
  490.                     }
  491.                     break;
  492.                 case f_TiledBitmap:
  493.                 case f_clippedBitmap:
  494.                     fillLineBitmap(f, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC);
  495.                     break;
  496.                 case f_LinearGradient:
  497.                     fillLineLG(&f->gradient, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC);
  498.                     break;
  499.                 case f_RadialGradient:
  500.                     fillLineRG(&f->gradient, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC);
  501.                     break;
  502.             case f_None:
  503.             break;
  504.             }
  505.         }
  506.     }
  507. }
  508.  
  509. /* draw the current path */
  510. void
  511. GraphicDevice::drawPolygon(void)
  512. {
  513.     long y;
  514.     Segment *curSegs,*seg;
  515.  
  516.     // no segments ? 
  517.     if (this->ymax == -1)
  518.         return;
  519.  
  520.     // Foreach scanline
  521.     curSegs = 0;
  522.     for(y=this->ymin; y <= this->ymax; y++) {
  523.         
  524.         // Make X values progess and remove unuseful segments
  525.         curSegs = progressSegments(curSegs, y);
  526.         
  527.         // Add the new segment starting at the y position.
  528.         curSegs = newSegments(curSegs, this->segs[y]);
  529.         
  530.         // Render the scanline
  531.         if (this->scan_line_func == NULL) {
  532.             renderScanLine(y, curSegs);
  533.         } else {
  534.             for(seg = curSegs; seg && seg->nextValid; seg = seg->nextValid) {
  535.                 if (seg->nextValid->X >= seg->X) {
  536.                     scan_line_func(this->scan_line_func_id, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC);
  537.                 }
  538.             }
  539.         }
  540.     }
  541.  
  542.     /* free the segments */
  543.     memset(this->segs + this->ymin, 0, 
  544.            (this->ymax - this->ymin + 1) * sizeof(Segment *)); 
  545.         
  546.     this->ymax = -1;
  547.     this->ymin = this->height;
  548.  
  549.     this->seg_pool_cur = this->seg_pool;
  550. }
  551.  
  552. void
  553. GraphicDevice::updateClippingRegion(Rect *rect)
  554. {
  555.     if (!clipping) return;
  556.  
  557.     transformBoundingBox(&clip_rect, adjust, rect, 1);
  558.     clip_rect.xmin >>= FRAC_BITS;
  559.     clip_rect.xmax >>= FRAC_BITS;
  560.     clip_rect.ymin >>= FRAC_BITS;
  561.     clip_rect.ymax >>= FRAC_BITS;
  562.  
  563.     clip_rect.xmin-=2;
  564.     clip_rect.ymin-=2;
  565.     clip_rect.xmax+=2;
  566.     clip_rect.ymax+=2;
  567.  
  568.     if (clip_rect.xmin < viewPort.xmin) clip_rect.xmin = viewPort.xmin;
  569.     if (clip_rect.xmax < viewPort.xmin) clip_rect.xmax = viewPort.xmin;
  570.     if (clip_rect.ymin < viewPort.ymin) clip_rect.ymin = viewPort.ymin;
  571.     if (clip_rect.ymax < viewPort.ymin) clip_rect.ymax = viewPort.ymin;
  572.  
  573.     if (clip_rect.xmax > viewPort.xmax) clip_rect.xmax = viewPort.xmax;
  574.     if (clip_rect.ymax > viewPort.ymax) clip_rect.ymax = viewPort.ymax;
  575.     if (clip_rect.xmin > viewPort.xmax) clip_rect.xmin = viewPort.xmax;
  576.     if (clip_rect.ymin > viewPort.ymax) clip_rect.ymin = viewPort.ymax;
  577. }
  578.  
  579. void
  580. GraphicDevice::setClipping(int value)
  581. {
  582.     clipping = value;
  583.     if (clipping == 0) {
  584.         // Reset region
  585.         clip_rect.xmin = viewPort.xmin;
  586.         clip_rect.xmax = viewPort.xmax;
  587.         clip_rect.ymin = viewPort.ymin;
  588.         clip_rect.ymax = viewPort.ymax;
  589.     }
  590. }
  591.  
  592. // Virtual
  593. void
  594. GraphicDevice::clearCanvas()
  595. {
  596. }
  597.  
  598. long
  599. GraphicDevice::allocColor(Color color)
  600. {
  601.     return 0;
  602. }
  603.  
  604. void
  605. GraphicDevice::fillLineBitmap(FillStyleDef *f, long y, long start, long end)
  606. {
  607. }
  608.  
  609. void
  610. GraphicDevice::fillLineLG(Gradient *grad, long y, long start, long end)
  611. {
  612. }
  613.  
  614. void
  615. GraphicDevice::fillLineRG(Gradient *grad, long y, long start, long end)
  616. {
  617. }
  618.  
  619. void
  620. GraphicDevice::fillLine(FillStyleDef *f, long y, long start, long end)
  621. {
  622. }
  623.  
  624. void
  625. GraphicDevice::fillLineAA(FillStyleDef *f, long y, long start, long end)
  626. {
  627. }
  628.  
  629. void
  630. GraphicDevice::drawLine(long x1, long y1, long x2, long y2, long width)
  631. {
  632. }
  633.